<?php
/**
 * Created by Administrator
 * User: longli
 * VX: isa1589518286
 * Date: 2020/08/20
 * Time: 18:00
 * @link http://www.lmterp.cn
 */

namespace app\common\service\channel;

use app\common\library\Tools;
use app\common\model\Channel;
use app\common\model\ChannelSender;
use app\common\model\Orders;
use app\common\service\BaseService;
use app\common\service\export\Order;
use think\facade\Config;

/**
 * 物流渠道对接基类
 * Class BaseChannel
 * @package app\common\service\channel
 */
abstract class BaseChannel extends BaseService
{
    /**
     * 渠道
     * @var Channel
     */
    protected $channel;

    /**
     * 发件人
     * @var ChannelSender
     */
    protected $sender;

    /**
     * token 字段约束
     * @var array
     */
    public static $tokenField = [
        'required' => [], // 必填字段
        'option' => [], // 可选字段
    ];

    /**
     * 需要处理的订单
     * @var Orders
     */
    protected $order;

    /**
     * @param int $channelId 渠道 id
     * @param int $senderId 发件人 id，如果为0则取默认值
     */
    public function __construct($channelId, $senderId = 0)
    {
        $this->setChannel($channelId);
        $this->setSender($senderId);
        $this->init();
    }

    /**
     * 初始化方法
     * @date 2020/09/04
     * @author longli
     */
    public function init(){}

    /**
     * 获取追踪号信息
     * @date 2020/08/21
     * @author longli
     * @return string|false 追踪号
     */
    abstract public function getTrackNumber();

    /**
     * 获取面单
     * @date 2020/08/21
     * @author longli
     * @return string|false 面单在本服务器的路径
     */
    abstract public function getLabel();

    /**
     * 检测对接渠道类是否存在
     * @param string $className 类名，不需要全类名
     * @return bool
     * @date 2020/09/17
     * @author longli
     */
    public static function classesExist($className = '')
    {
        if(!Tools::startWith($className, '\\')) $className = static::getClasses($className);
        return class_exists($className);
    }

    /**
     * 获取对接渠道的全类名
     * @param string $className 类名
     * @return string
     * @date 2020/09/17
     * @author longli
     */
    public static function getClasses($className = '')
    {
        return '\app\common\service\channel\\' . $className;
    }

    /**
     * 试算运费
     * @param array $data 如果 $data 为空则使用订单计算
     * @date 2020/08/21
     * @return array 返回计算结果 ['weight' => 1, 'logistics_price' => 1.0]
     *@author longli
     * @example
     *  $data = [
     *      "sku" => [
     *          'A001' => 2,
     *          'A002' => 1,
     *       ],
     *      "country_code" => "US"
     * ];
     */
    public function computeCharge($data = [])
    {
        return [];
    }

    /**
     * 获取物流信息
     * @param string|string[] $trackNum 追踪号如果为空则空订单中获取
     * @return string
     * @date 2020/08/21
     * @author longli
     */
     public function getTrackInfo($trackNum = '')
     {
         return "";
     }

    /**
     * 获取订单运费
     * @return float
     * @date 2021/02/23
     * @author longli
     */
     public function getPrice()
     {
        return 0;
     }

    /**
     * 取消订单
     * @return bool
     * @date 2020/08/21
     * @author longli
     */
    public function cancelOrder()
    {
        return false;
    }

    /**
     * 拦截订单
     * @param string $remark 拦截原因
     * @return bool
     * @date 2021/02/23
     * @author longli
     */
    public function interceptOrder($remark = '')
    {
        return false;
    }

    /**
     * 保存面单为 PDF 格式
     * @param string $byte 面单字节
     * @param string $suffix 文件名后缀，默认为 pdf
     * @return string 面单在本服务器中的路径
     * @date 2020/08/23
     * @author longli
     */
    public static function saveLabel($byte, $suffix = 'pdf')
    {
        if(Tools::startWith($suffix,'.')) $suffix = substr($suffix, 1);
        $labelPath = Config::get("label_path");
        $fileName = $labelPath . Tools::getRandStr(23) . ".$suffix";
        if(!is_dir($labelPath)) mkdir($labelPath, 0777, true);
        file_put_contents($fileName, $byte);
        return self::hiddenRootPath($fileName);
    }

    /**
     * 重置订单物流状态
     * @return bool
     * @date 2020/09/26
     * @author longli
     */
    public function resetOrderStatus()
    {
        //$this->order->order_status = Orders::ORDER_WAIT;
        $this->order->send_status = Orders::SEND_WAIT;
        $this->order->is_print = Orders::PRINT_N;
        $this->order->logistics_name = "";
        $this->order->logistics_price = 0;
        $this->order->label_url = "";
        $this->order->track_num = "";
        return $this->order->save();
    }

    /**
     * 获取所有平台对接 Service 服务
     * @return array
     * @date 2020/09/24
     * @author longli
     */
    public static function getAllChannelService()
    {
        return self::getAllService(__DIR__, Tools::classBasename(__CLASS__));
    }

    public function setChannel($channelId)
    {
        $this->channel = Channel::getOrFail($channelId);
    }

    public function setSender($senderId)
    {
        $where = !empty($senderId) ? ['sender_id' => $senderId] : ['is_default' => ChannelSender::IS_YES];
        $where['status'] = ChannelSender::IS_YES;
        if(!($this->sender = ChannelSender::get($where)))
            throw new \RuntimeException("预报订单失败，未能获取到发货人信息");
    }

    /**
     * @param Orders $order
     */
    public function setOrder(Orders $order)
    {
        $this->order = $order;
        // 检测账号是否有绑定发货地址
        if($sender = ChannelSender::getByAccount($order->account_id)) $this->sender = $sender;
    }

    /**
     * @return Orders
     */
    public function getOrder()
    {
        return $this->order;
    }
}